#!/bin/bash

# Copyright (C) 2011 toytoygogie. All rights reserved.
# License to GNU/GPL. To read the license, see http://www.gnu.org/licenses/gpl.html
# Limitations for using this script is according to the license.
# This program is distributed in the hope that it will be useful, but 
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# for more details

# The purpose of this script is to upload files having the same directory
# structure into the ftp. 
# You can also upload the files via ftp into an empty root directory, since 
# the script will check if the directory is existent, else it will create that directory
# before uploading the file. The script also detects if the file is set to upload as ascii or binary
#
# To run the program upload the files modified last 24 hours,
#
#  $> . auto-ftp-relocator.sh "-1440"
#
#



# You can replace ${DEF_BASEDIR} here or do define `export DEF_BASEDIR=/your/base/path` like in you .bash_profile or .bashrc
# BASE_DIR is the source directory where the files reside for uploading to another directory, the same contents or target as
# the BASE_DIR. 
BASE_DIR=${DEF_BASEDIR}
cd $BASE_DIR

# You can replace the path wherever you want
LOGDIR=/var/log/bash-auto-ftp/
LOGFILE=autoftp.log
IS_EXCLUDE=FALSE 

HOST='ftp.hostname.com'
USER='username'
# if your username has '@' (at) symbol, just uncomment below and use the same format below
#USER_UDECODE='user%40hostname.com' 
USER_UDECODE=$USER 
PASSWD='yourpassword'

[ -z $1 ] && min="-1500" || min="$1"
# If you want to exclude *.svn files, else, just modify the command below
FN_FILES=`find . -mmin $min|grep -r -E "*.svn*" -v`

# Make "./" as the prefix of the values inside indices
declare -a EXCLUDED_FILES=(
	"."
	"./Thumbs.db"
	"./cache"
	"./sql-dumps"
	"./websites"
	"./footertpl.mod.php"
	"./.project"
	"./.buildpath"
	"./config.inc.php"
	"./.project2"
	"./.htaccess"
	"./headertpl.mod.php"
	"./.externalToolBuilders"
	"./template.php"
	"./.settings"
	".DS_Store"
)

CUR_FILE_DIR="" 
CUR_FILE="" 
CACHE_FILES=""
CACHE_EXCLUDED_FILES=""

fn_get_path() {

    CUR_FILE_DIR=""
    CUR_FILE_DIR=`dirname $1`
    
}

fn_do_log() {

	cat >> "$LOGDIR/$LOGFILE" << EOF
---------------------------------------------------------------------
[ `date +"%Y/%m/%d %I:%M:%S %p"` - below is what the script transfer to ftp is doing :-) ]
`echo -e ${CACHE_FILES}`

---------------------------------------------------------------------
<---- listing the excluded files during upload ------>
`echo -e ${CACHE_EXCLUDED_FILES}`
=====================================================================



EOF

}


fn_cached_file() {
    local ftp_dir=""
    local filecmd=""
    #ftp_dir=`expr index "${CUR_FILE_DIR}" "./"` # not working since OS X is using BSD expr, Linux is GNU expr
	index=${#CUR_FILE_DIR}-$(echo $CUR_FILE_DIR|sed -n "s/\.\///p" | wc -c)
	ftp_dir=${CUR_FILE_DIR:$index}

	if [ "${CUR_FILE_DIR}" == "." ]; then
		ftp_dir="/"
	else
		index=${#CUR_FILE_DIR}-$(echo $CUR_FILE_DIR|sed -n "s/\.\///p" | wc -c)
		ftp_dir=${CUR_FILE_DIR:$index}
	fi

	file "${BASE_DIR}/${CUR_FILE_DIR}/${CUR_FILE}" |egrep "ascii|text" >/dev/null 2>&1
    
    if [ $? -eq 0 ];then
    	filecmd="ascii"
    else
    	filecmd="binary"   
    fi	
	
    CACHE_FILES="
${CACHE_FILES}
cd ${ftp_dir}\n    
lcd ${BASE_DIR}/${CUR_FILE_DIR}\n ${filecmd}\n
put ${CUR_FILE}\n"
}


fn_ftp_mkdir() {
    local ftp_dir=""
    local curDir=$1
    local baseDir=$2
    
	# Remove the (.) dot character, then take the index (tested only on Mac OS X)
	#index=${#curDir}-$(echo $curDir|sed -n "s/\.\///p" | wc -c)
	#ftp_dir=${curDir:$index}

	if [ "${baseDir}" == "." ]; then
		baseDir="/"
	else
		index=${#baseDir}-$(echo $baseDir|sed -n "s/\.\///p" | wc -c)
		baseDir=${baseDir:$index}
	fi

    CACHE_FILES="
${CACHE_FILES}
cd ${baseDir}\n
mkdir ${curDir}\n"
}

fn_do_ftp_upload() {
	ftp -i -n $HOST <<EOF
	user ${USER} ${PASSWD}
	`echo -e ${CACHE_FILES}`
	quit
EOF
}

fn_is_dir() {
	if [ -d "$1" ]; then 
		echo TRUE
	else
		echo FALSE
	fi
}

fn_check_for_exclusion() {
	
	IS_EXCLUDE=FALSE
	
	local compareBaseDir=''
	local curFile=$1
	local exFLen=0
	local bcurFile=`basename $1`
	
	for exF in ${EXCLUDED_FILES[*]}
	do
		if [[ "$exF" != "." && -d "$exF" ]]; then
			exFLen=${#exF}
			compareBaseDir=${curFile:0:exFLen}
			
			if [ "$exF" == "$compareBaseDir" ]; then
				IS_EXCLUDE=TRUE
				CACHE_EXCLUDED_FILES=$CACHE_EXCLUDED_FILES`cat << EOF
		excluding file: ${f}\n 			
EOF`
				
				echo "file is in exclusion, because its basDir is excluded -> ${curFile}"
				echo "while comparing ${exF} to ${compareBaseDir}"
				
				break
			fi
		fi
		
		if [[ "$exF" == "$1" || "$exF" == "${bcurFile}" ]]; then
			IS_EXCLUDE=TRUE
			CACHE_EXCLUDED_FILES=$CACHE_EXCLUDED_FILES`cat << EOF
	excluding file: ${f}\n 			
EOF`
				echo "file is in exclusion -> ${curFile}"
			break
		fi
	done
}


fn_check_if_dir_exist() {
	local curFile=$1
	local test=`ftp ftp://"${USER_UDECODE}":"${PASSWD}"@${HOST}:21/${curFile}`
	echo | awk -v test="${test}" 'BEGIN {print index(test, "No such file or directory")}'
}

for f in $FN_FILES 
do
	fn_check_for_exclusion $f

	if $IS_EXCLUDE ; then
		continue
	fi
	
    CUR_FILE=`basename $f`
    echo "found file is : ${f}"    

    fn_get_path $f
    
    if [ -d $f ]; then
    	index=`fn_check_if_dir_exist $f`
		if [ $index -gt 0 ]; then
			fn_ftp_mkdir $CUR_FILE $CUR_FILE_DIR
		fi
    else
    	fn_cached_file
    fi

done

fn_do_log
fn_do_ftp_upload
